package com.afalon.cloud.rest.system;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.DELETE;
import javax.ws.rs.Path;
import javax.ws.rs.PUT;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.QueryParam;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import java.net.URI;
import java.util.*;

import com.afalon.cloud.contracts.system.SenchaEnvelope;
import com.afalon.cloud.contracts.system.User;
import com.sun.jersey.api.JResponse;
import com.google.appengine.api.datastore.KeyFactory;
import com.afalon.cloud.PMF;
import com.afalon.cloud.Session;

@Path("/system")
public class RestSystem {

	@GET
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/users/{userid}")
	public JResponse<User> getUser(
			@PathParam("userid") String userId,
			@Context HttpServletRequest request,
			@Context UriInfo uriInfo) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			User user = pm.getObjectById(User.class, userId);
			if (user == null) {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			} else {
				user.userUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path("system/users").path(user.getUserId()).build();
				return JResponse.ok(user).build();
			}
		} finally {
			pm.close();
		}
	}

	@GET
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/users")
	public JResponse<List<User>> getUsers(
			@QueryParam("logon") String logOn,
			@QueryParam("personid") String personId,
			@Context HttpServletRequest req,
			@Context UriInfo uriInfo) {
		Session.Authenticated(req);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(User.class);
		if (logOn != null) {
			query.setFilter("logon == '" + logOn + "'");
		}
		if (personId != null) {
			query.setFilter("personid == '" + personId + "'");
		}
		try {
			@SuppressWarnings("unchecked")
			List<User> users = (List<User>) query.execute();
			if (users.iterator().hasNext()) {
				for (User user : users) {
					user.userUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path("system/users").path(user.getUserId()).build();
				}
				return JResponse.ok(users).build();
			} else {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			}
		} finally {
			query.closeAll();
		}
	}

	@POST
	@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/users")
	public Response postUser(
			User user, 
			@Context HttpServletRequest req) {
		Session.Authenticated(req);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			pm.makePersistent(user);
			return Response.created(
					URI.create(KeyFactory.keyToString(user.getUserKey())))
					.build();
		} finally {
			pm.close();
		}
	}

	@PUT
	@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/users/{userid}")
	public Response putUser(
			User user, 
			@PathParam("userid") String userId,
			@Context HttpServletRequest req,
			@Context UriInfo uriInfo) {
		Session.Authenticated(req);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			User userResult = pm.getObjectById(User.class, userId);
			if (userResult == null) {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			} else {
				if (user.getLogon()!=null && !user.getLogon().isEmpty() && user.getLogon()!=userResult.getLogon()) {
					userResult.setLogon(user.getLogon());
				}
				if (user.getPassword()!=null && !user.getPassword().isEmpty() && user.getPassword()!=userResult.getPassword()) {
					userResult.setPassword(user.getPassword());
				}
				pm.makePersistent(userResult);
				userResult.userUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path("system/users").path(userResult.getUserId()).build();
				return Response.ok(userResult).build();
			}
		} finally {
			pm.close();
		}
	}

	@DELETE
	@Path("/users/{userid}")
	public Response deleteUser(
			@PathParam("userid") String userId,
			@Context HttpServletRequest request) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			User user = pm.getObjectById(User.class, userId);
			if (user == null) {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			} else {
				pm.deletePersistent(user);
				return Response.noContent().build();
			}
		} finally {
			pm.close();
		}
	}

	@GET
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/users/sample")
	public JResponse<SenchaEnvelope<User>> getSampleUser(@Context HttpServletRequest request,
			@Context UriInfo uriInfo) {
		// Session.Authenticated(request);
		SenchaEnvelope<User> userEnvelope = new SenchaEnvelope<User>(Boolean.TRUE, "User Created");
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(User.class);
		try {
			query.setUnique(true);
			query.setFilter("logon == logonParam");
			query.declareParameters("String logonParam");
			User user = (User) query.execute("TestUser");
			if (user == null) {
				User newuser = new User();
				newuser.setLogon("TestUser");
				newuser.setPassword("password");
				newuser.userUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path("system/users").path(user.getUserId()).build();
				pm.makePersistent(newuser);
				userEnvelope.setData(newuser);
				return JResponse.ok(userEnvelope).build();
			} else {
				userEnvelope.setData(user);
				return JResponse.ok(userEnvelope).build();
			}
		} finally {
			query.closeAll();
			// pm.close();
		}

	}
}
